#include "LZW.h"
#include <fstream>
#include <iostream>

using std::cout;
using std::ofstream;

LZW::LZW()
{
	int i;
	char c; // 这里一定要用一个char来表示，因为char的一字节大小恰好可以表示0-255，而to_string(int)生成的是字符串，将使我们无法还原编码
	string key = "";
	bitset<16> value;
	for (i = 0; i < 256; i++) // 初始化0-255像素值的编码
	{
		key = "";
		c = i;
		key += c; // 这里一定要使用空string拼接c，如果用c+""就会错误
		value = i;
		dictionary.insert(make_pair(key, value));
	}
	last_code = "";
	code_value = 256;
	dic_size = 256; // 初始大小为256
}

LZW::~LZW()
{
	if (dictionary.size() != 0)
		dictionary.clear();
	if (encode_result.size() != 0)
		encode_result.clear();
	if (decode_result.size() != 0)
		decode_result.clear();
	last_code = "";
	code_value = 256;
	dic_size = 256;
}

void LZW::printDict()
{
	cout << "字典内容如下:\n\n"
			"字符\t值\n";
	for (auto it = dictionary.begin(); it != dictionary.end(); it++)
	{
		cout << it->first << '\t' << it->second << '\n';
	}
	cout << '\n';
}

void LZW::outputDict(const char *cFilename)
{
	ofstream outfile;
	outfile.open(cFilename, std::ios::out);
	if (!outfile.is_open())
	{
		cout << "Open file failure\n";
		outfile.close();
		return;
	}

	for (auto it = dictionary.begin(); it != dictionary.end(); it++)
	{
		outfile << it->first << '\t' << it->second << '\n';
	}
	outfile.close();
}

bool LZW::dict_is_full()
{
	if (dic_size == 65536)
		return true;
	else
		return false;
}

void LZW::dict_reset()
{
	dictionary.clear(); //先将已满的字典清空
	int i;
	char c;
	string key = "";
	bitset<16> value;
	for (i = 0; i < 256; i++) //初始化0-255像素值的编码
	{
		key = "";
		c = i;
		key += c; //这里一定要使用空string拼接c，如果用c+""就会错误
		value = i;
		dictionary.insert(make_pair(key, value));
	}
	dic_size = 256;
	code_value = 256;
	//注意last_code不改变
}

void LZW::decode_table_reset(map<bitset<16>, string, bitset_comparer<16>> &decode_table)
{
	decode_table.clear(); // 先将已满的字典清空
	map<string, bitset<16>>::iterator temp_it;
	for (temp_it = dictionary.begin(); temp_it != dictionary.end(); temp_it++)
	{
		decode_table.insert(make_pair(temp_it->second, temp_it->first));
	}
	dic_size = 256;
	code_value = 256;
	// 注意last_code不改变
}

void LZW::encoding(const string &s)
{
	last_code = ""; // 初始状态，上一次编码置空
	string null = "";
	bitset<16> value;
	for (auto s_it = s.begin(); s_it != s.end(); s_it++)
	{
		if (dict_is_full()) // 字典满了就重置
		{
			dict_reset();
		}

		if (dictionary.find(last_code + *s_it) != dictionary.end())
			last_code = last_code + *s_it; // 直到找到最长前缀，进入else
		else
		{
			encode_result.push_back(dictionary[last_code]);
			value = code_value++;
			dictionary.insert(make_pair(last_code + *s_it, value));
			dic_size++;
			last_code = null + *s_it;
		}
	}

	if (last_code != "") //最后一次的输出
	{
		encode_result.push_back(dictionary[last_code]);
	}
}

void LZW::decoding(const vector<bitset<16>> &s)
{
	map<bitset<16>, string, bitset_comparer<16>> decode_table; // 建立一个键值互换的表用来加速解码
	decode_table_reset(decode_table);

	last_code = "";
	string c = ""; // c for current，当前解码字符
	bitset<16> key;
	for (auto it = s.begin(); it != s.end(); it++)
	{
		if (dic_size % 65536 == 0) // 注意这个数值是pow(2,n)，n是bitset位数
		{
			decode_table_reset(decode_table);
		}
		if (decode_table.find(*it) != decode_table.end())
			c = decode_table[*it];
		else
		{
			if ((*it).to_ulong() == code_value) // 当出现连续的同字符编码，可能会超过字典已有范围
				c += c[0];
			else
			{
				cout << "当前编码：" << (*it).to_ulong() << '\n';
				cout << "code_value:" << code_value << '\n';
				cout << "编码错误\n";
				exit(1);
			}
		}
		if (last_code != "")
		{
			key = code_value++;
			decode_table.insert(make_pair(key, last_code + c[0]));
			dic_size++;
		}
		decode_result += c;
		last_code = c;
	}
}

vector<bitset<16>> &LZW::get_encode_result()
{
	return encode_result;
}

string &LZW::get_decode_result()
{
	return decode_result;
}

string Byte2Binary(char buffer) // 将一个字节转换成8bit保存到字符串
{
	string s; // 返回字符串
	unsigned char *p, ch;
	int i, j;
	p = (unsigned char *)(&buffer);
	for (i = sizeof(buffer) - 1; i >= 0; i--)
	{
		ch = *(p + i);
		for (j = 0; j < 8; j++)
		{
			if ((ch << j) & 0x80) // 0x80即128，二进制表示1000 0000，这里操作目的是取最高位
				s += '1';
			else
				s += '0';
		}
	}
	return s;
}